package cn.tedu.oa_system.service.impl;

import cn.tedu.oa_system.base.json_result.ResultDataDto;
import cn.tedu.oa_system.base.json_result.ResultDto;
import cn.tedu.oa_system.base.util.DateUtil;
import cn.tedu.oa_system.mapper.AttendsMapper;
import cn.tedu.oa_system.mapper.UserMapper;
import cn.tedu.oa_system.pojo.Attends;
import cn.tedu.oa_system.pojo.User;
import cn.tedu.oa_system.pojo.in.FindLikeKeyIn;
import cn.tedu.oa_system.pojo.in.PageIn;
import cn.tedu.oa_system.pojo.model.UserInfo;
import cn.tedu.oa_system.pojo.vo.AttendsVO;
import cn.tedu.oa_system.service.AttendsService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;

import static cn.tedu.oa_system.base.constant.DataBaseConstants.DATABASE_AFFECTED_ROW;

/**
 * @Author MW
 * @Description 考勤服务接口实现类
 * @CreateDate 2023/3/1
 */
@Slf4j
@Service
@Transactional
public class AttendsServiceImpl implements AttendsService {

    @Autowired
    private AttendsMapper attendsMapper;

    @Autowired
    private UserMapper userMapper;

    /**
     * 签到,添加考勤数据
     * @return
     */
    @Override
    public ResultDto<AttendsVO> signIn() {
        ResultDto<AttendsVO> resultDto=new ResultDto<>();
        //通过security上下文获取签到人信息
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        log.debug("根据security上下文中获取的username为:({})",name);
        //根据用户名获取用户信息
        UserInfo userInfo = userMapper.getUserInfoByUsername(name);
        //获取ip
        String ip=null;
        try {
            ip=InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        log.debug("获取到当前用户的ip为:({})",ip);
        //规范上下班时间   8点上班  17点下班
        String start="08:00:00", end="17:00:00";
        //签到状态类型默认为正常    statusId: 10为正常  11为迟到   12为早退
        long statusId=10, typeId=10;
        //获取当前签到时间,判断当下时间是否能签到
        String current = DateUtil.now(DateUtil.DATE_FORMAT_TIME);
        log.debug("当前时间为:{}",current);
        String today = DateUtil.now(DateUtil.DATE_FORMAT_DATE);
        String weekOfDay = DateUtil.weekOfDay();

        Attends attends=new Attends();

        if (current.compareTo("05:00:00")<0){
            //若当前时间未到凌晨5点,且未曾点过签到, 则未到签到时间,签到无效
            log.debug("未到凌晨5点,签到无效");
            resultDto.setMes("还未到有效签到时间");
            return resultDto;
        } else if ((current.compareTo("05:00:00")>0)&&(current.compareTo(end)<0)){
            //到这为能有效签到,每个用户每天只能产生两条记录
            //根据当天日期和用户信息查找用户当天的考勤记录,并作出判断
            int count = attendsMapper.countByToday(today, name);
            log.debug("今天的签到累计次数为:{}",count);
            if (count==0){
                //若记录为0时,说明用户今天是第一次签到,则判断签到时间为正常/迟到/旷工,并添加考勤记录
                if (current.compareTo(end)>0){
                    //若当前时间比下班时间晚,则签到无效,
                    resultDto.setMes("已过有效签到时间,签到无效");
                    return resultDto;
                }
                if (current.compareTo(end)<0){
                    //若此时为下班时间之前,可以签到,判断签到时间状态
                    //设置签到类型    上班type:typeId:8
                    typeId=8;
                    if (current.compareTo(start)>0){
                        //若此时晚于上班时间 则迟到,设置状态id
                        statusId=11;
                    }
                    //到这为早于上班时间,默认为正常,根据以上数据添加考勤记录
                    //根据用户名获取用户id并存入考勤记录
                    attends.setAttendsUserId(userInfo.getId());
                    attends.setTypeId(typeId);
                    attends.setStatusId(statusId);
                    attends.setAttendsTime(new Date());
                    attends.setAttendTime(current);
                    attends.setWeekOfDay(weekOfDay);
                    attends.setAttendsIp(ip);
                    log.debug("准备添加的考勤记录为:{}",attends);
                    int i=attendsMapper.insert(attends);
                    Assert.isTrue(i==DATABASE_AFFECTED_ROW,"签到失败,请重试");
                }
            }
            if (count==1){
                //若记录为1时,说明用户今天是第二次签到,为签退下班,判断签退时间为正常/早退,并添加考勤记录
                //凌晨之前要签退,不然过了凌晨则为第二天的考勤记录
                //设置类型id为9   下班
                log.debug("今天的签到累计次数为:{}",count);
                typeId=9;
                if (current.compareTo(end)<0){
                    //若此时早于下班时间, 则为早退  设置状态id为 12
                    statusId=12;
                }
                //代码到这说明正常下班,根据以上数据添加考勤记录
                attends.setAttendsUserId(userInfo.getId());
                attends.setTypeId(typeId);
                attends.setStatusId(statusId);
                attends.setAttendsTime(new Date());
                attends.setAttendTime(current);
                attends.setWeekOfDay(weekOfDay);
                attends.setAttendsIp(ip);
                log.debug("准备添加的考勤记录为:{}",attends);
                int i=attendsMapper.insert(attends);
                Assert.isTrue(i==DATABASE_AFFECTED_ROW,"签退失败,请重试");
            }
            if (count>=2){
                log.debug("今天的签到累计次数为:{}",count);
                //若记录大于等于2,说明用户今天至少为第三次签到,已是下班状态,这里是更改考勤时间,判断与签退一致,并根据新的ip,时间,状态更改签退考勤记录
                if (current.compareTo(end)<0){
                    //若此时早于下班时间, 则为早退  设置状态id为 12
                    statusId=12;
                }
                //代码到这说明正常下班,根据以上数据更改考勤记录
                attends.setStatusId(statusId);
                attends.setAttendsTime(new Date());
                attends.setAttendTime(current);
                attends.setAttendsIp(ip);
                long attendsId = attendsMapper.findOffWorkId(today, name);
                log.debug("准备修改的考勤记录id为:{}",attendsId);
                attends.setAttendsId(attendsId);
                log.debug("准备修改的考勤记录为:{}",attends);
                int i = attendsMapper.updateById(attends);
                Assert.isTrue(i==DATABASE_AFFECTED_ROW,"更改考勤失败,请重试");
            }
        }
        //返回用户当天的最新考勤记录 用于显示考勤状态
        log.debug("当前类型id为:{}",typeId);
        log.debug("当前状态id为:{}",statusId);
        AttendsVO listAttends = attendsMapper.findLastAttends(today, name);
        resultDto.setData(listAttends);
        resultDto.setIsSuccess(true);
        return resultDto;
    }

    /**
     * 查询考勤列表
     * @param pageIn
     * @return
     */
    @Override
    public ResultDataDto<AttendsVO> listOfAll(PageIn pageIn) {
        log.debug("正在获取考勤列表.....");
        Page<AttendsVO> page=new Page<>(pageIn.getCurrent(),pageIn.getSize());
        ResultDataDto<AttendsVO> resultDataDto = new ResultDataDto<>();
        IPage<AttendsVO> attendsIPage = attendsMapper.listOfAll(page);
        List<AttendsVO> records = attendsIPage.getRecords();
        resultDataDto.setTotal(attendsIPage.getTotal());
        resultDataDto.setDataList(records);
        resultDataDto.setIsSuccess(true);
        return resultDataDto;
    }

    /**
     * 考勤列表模糊查询
     * @param likeKeyIn
     * @return
     */
    @Override
    public ResultDataDto<AttendsVO> findLikeKeyOfAll(FindLikeKeyIn likeKeyIn) {
        log.debug("正在根据({})考勤列表.....", likeKeyIn.getLikeKey());
        Page<AttendsVO> page=new Page<>(likeKeyIn.getCurrent(), likeKeyIn.getSize());
        ResultDataDto<AttendsVO> resultDataDto = new ResultDataDto<>();
        IPage<AttendsVO> attendsIPage = attendsMapper.findLikeKeyOfAll(page, likeKeyIn);
        List<AttendsVO> records = attendsIPage.getRecords();
        resultDataDto.setTotal(attendsIPage.getTotal());
        resultDataDto.setDataList(records);
        resultDataDto.setIsSuccess(true);
        return resultDataDto;
    }

    /**
     * 个人考勤表查询
     * @param pageIn
     * @return
     */
    @Override
    public ResultDataDto<Attends> listOfSelf(PageIn pageIn) {
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        log.debug("根据security上下文中获取的username为:({})",name);
        Page<Attends> page=new Page<>();
        page.setCurrent(pageIn.getCurrent());
        page.setSize(pageIn.getSize());
        ResultDataDto<Attends> resultDataDto = new ResultDataDto<>();
        IPage<Attends> attendsIPage = attendsMapper.listOfSelf(page, name);
        List<Attends> records = attendsIPage.getRecords();
        resultDataDto.setTotal(attendsIPage.getTotal());
        resultDataDto.setDataList(records);
        resultDataDto.setIsSuccess(true);
        return resultDataDto;
    }

    /**
     * 个人考勤列表模糊查询
     * @param likeKeyIn
     * @return
     */
    @Override
    public ResultDataDto<AttendsVO> findLikeKeyOfSelf(FindLikeKeyIn likeKeyIn) {
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        log.debug("根据security上下文中获取的username为:({})",name);
        Page<AttendsVO> page=new Page<>(likeKeyIn.getCurrent(),likeKeyIn.getSize());
        ResultDataDto<AttendsVO> resultDataDto = new ResultDataDto<>();
        IPage<AttendsVO> attendsIPage = attendsMapper.findLikeKeyOfSelf(page, likeKeyIn,name);
        List<AttendsVO> records = attendsIPage.getRecords();
        resultDataDto.setTotal(attendsIPage.getTotal());
        resultDataDto.setDataList(records);
        resultDataDto.setIsSuccess(true);
        return resultDataDto;
    }

}
